{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "1cc4fb3e",
   "metadata": {},
   "source": [
    "# Une première carte - Métro 4\n",
    "\n",
    "Nous avons à notre disposition les positions GPS des stations de métro de la ligne 4. Nous souhaitons afficher sur un carte ces stations. Pour cela, allons réaliser un programme Python. Nous veillerons à ce que l'organisation soit la plus correcte et notre code aussi clair que possible.\n",
    "\n",
    "Nous allons suivre le shéma suivant.\n",
    "1. Lire le fichier de données\n",
    "2. Préparer les données Python\n",
    "3. Créer la carte\n",
    "\n",
    "La première partie consiste à lire un fichier de données et les convertir en quelque chose d'interprétable pour Python. La deuxième partie sera nécessaire pour préparer les données, c'est à dire, filter celles qui ne sont pas pertinentes et convertir les données au format le plus adapté. Nous pourrons alors réaliser la troisième partie dédiée à la création de la carte.\n",
    "\n",
    "Pour les plus motivé.e.s, on découvrira comment améliorer notre projet en complétant les données corrompues plutôt qu'en les filtrant.\n",
    "\n",
    "Le schéma suivant récapitule le processus qui nous attend. Il vous représente la nature des données que l'on traite après l'appel de chacune des fonctions.\n",
    "\n",
    "![Schéma directeur](../_static/images/premiere_carte/tuto.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a7e0b1b0",
   "metadata": {},
   "source": [
    "\n",
    "## Préparation du projet\n",
    "\n",
    "Commençons par créer un nouveau projet Replit et à y ajouter un répertoire `datas` pour y stocker le fichier contenant les données : {Download}`ligne4.txt<../_static/datas/ligne4.txt>`. Ouvrez le fichier {Download}`ligne4.txt<../_static/datas/ligne4.txt>` et regardez comment il est constitué.\n",
    "\n",
    "Il est constitué de lignes. Chaque ligne correspond à une station. Elle est divisée en trois colonnes avec la latitude, la longitude et le nom de la station. Les colonnes sont séparées par des virgules. Avec un peu d'attention, vous devriez remarquer que certaines lignes sont mal justifiées et d'autres sont même corrompues : des données manquent, au maximum une par ligne. Gardons cela en tête.\n",
    "\n",
    "Tout le code que nous allons créer devra être contenu dans le fichier `main.py`. Nous tacherons de le garder aussi propre que possible. Si vous avez des commentaires à écrire ou des notes pour le cours, faites le dans un autre fichier. **N'utilisez ce fichier que pour le code**, rien de plus.\n",
    "\n",
    "Passons à la première partie, la lecture des données.\n",
    "\n",
    "\n",
    "## Partie 1, lire un fichier texte\n",
    "\n",
    "Afin de ne pas trop se noyer dans les informations, je vous propose de considérer la fonction `read_file(name)` comme une boite noire. C'est une fonction qui lit un fichier et renvoie une liste qui contient les lignes contenues dans le fichier. Nous détaillerons plus tard dans le cours son fonctionnement.\n",
    "\n",
    "Notons tout de même que le paramètre `name` permet de désigner le fichier, c'est le chemin d'accès vers le fichier. L'origine de ce chemin est le répertoire contenant le fichier `main.py`. Dans notre cas, pour lire le fichier il faudra donc saisir l'instruction `read_file(\"datas/ligne4.txt\")`.\n",
    "\n",
    "```{code}\n",
    "def read_file(name):\n",
    "    lines = \"\"\n",
    "    with open(name) as f:\n",
    "        lines = f.readlines()\n",
    "    return lines\n",
    "    \n",
    "lines = read_file(\"datas/ligne4.txt\")\n",
    "```\n",
    "\n",
    "**Question** : Copier/coller dans `main.py` cette fonction et tester là.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "78f3bb0d",
   "metadata": {
    "tags": [
     "remove-cell"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['48.80350127856915, 2.3174291790534154, Bagneux - Lucie Aubrac \\n',\n",
       " '48.80991722995029, 2.317686671122904, Barbara \\n',\n",
       " '48.81862126138922, , Mairie de Montrouge \\n',\n",
       " \"  48.823057475209445    , 2.32596933256901, Porte d'Orléans \\n\",\n",
       " '48.828566875440806, 2.3272997082613656, Alésia \\n',\n",
       " '48.83167447533102, 2.3298317134834905  ,   Mouton Duvernet   \\n',\n",
       " '48.83411060896415, 2.3319309553749883,       Denfert-Rochereau\\n',\n",
       " '48.83928175949427, 2.331028353497835, Raspail \\n',\n",
       " ', 2.329089014624251, Vavin \\n',\n",
       " '48.84704045656309, 2.326945534873718, Saint-Placide\\n',\n",
       " '48.85170853073086,    2.3307476596845422, \\n',\n",
       " '48.85358907063822, 2.333758738461948, Saint-Germain-des-Prés\\n',\n",
       " '48.85244045451841, 2.33950819726021, Odeon \\n',\n",
       " '48.85381285231611, 2.3449980166801163, Saint-Michel Notre-Dame \\n',\n",
       " '   , 2.3469263403106098, Cité \\n',\n",
       " '48.85976498591345, 2.3470795833266136, Chatelet \\n',\n",
       " '48.86253891797647, 2.3459852420549647, Les Halles \\n',\n",
       " '48.8637670220375, 2.3488498413124623, Étienne Marcel\\n',\n",
       " '  48.86619467632844,   2.352378479150136, Réaumur - Sébastopol \\n',\n",
       " '48.869614705281734, 2.352901590258269, Strasbourg Saint-Denis \\n',\n",
       " \"48.872464986701324, 2.355897779221317, Château d'Eau \\n\",\n",
       " '48.87638992969864, 2.3578793464078913, \\n',\n",
       " '48.87956874846099, , Gare du Nord\\n',\n",
       " '48.88378548775286, 2.350607799296879, Barbès - Rochechouart\\n',\n",
       " ', 2.3498158594020095, Château Rouge \\n',\n",
       " '48.89151805255178, 2.350241633546168, Marcadet – Poissonniers\\n',\n",
       " '48.893987070119195, 2.3478658138599524, Simplon\\n',\n",
       " '48.898311313785584, 2.345121624270384, Porte de Clignancourt\\n']"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def read_file(name):\n",
    "    lines = \"\"\n",
    "    with open(name) as f:\n",
    "        lines = f.readlines()\n",
    "    return lines\n",
    "\n",
    "lines = read_file(\"../_static/datas/ligne4.txt\")\n",
    "lines"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8049f02d",
   "metadata": {},
   "source": [
    "**Question** : La première fonction que l'on va coder permet de découper une ligne. Créez une fonction `split_line(line)`. Cette fonction prend en paramètre une ligne et la décompose pour renvoyer une liste de trois valeurs.\n",
    "\n",
    "Ainsi,\n",
    "\n",
    "```split_line('48.828566875440806     , 2.3272997082613656, Alésia \\n')```\n",
    "\n",
    "doit nous renvoyer une la liste suivante :\n",
    "\n",
    "```[48.828566875440806     ', ' 2.3272997082613656', ' Alésia \\n']```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "0f4ead6b",
   "metadata": {},
   "outputs": [],
   "source": [
    "def split_line(l):\n",
    "    pass\n",
    "\n",
    "split_line('48.828566875440806     , 2.3272997082613656, Alésia \\n')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3b447356",
   "metadata": {},
   "source": [
    "Voici une correction possible.\n",
    "\n",
    "```{toggle} Correction.\n",
    "\n",
    "```{code}\n",
    "def split_line(l):\n",
    "    elts = l.split(\",\")\n",
    "    return elts\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "07e1fb94",
   "metadata": {},
   "source": [
    "**Question** : Améliorons cette fonction en supprimant les caractères blancs au début et à la fin des chaines de caractères que l'on obtient.\n",
    "\n",
    "Ainsi, \n",
    "\n",
    "```split_line('48.828566875440806     , 2.3272997082613656, Alésia \\n')```\n",
    "\n",
    "doit nous renvoyer une la liste suivante :\n",
    "\n",
    "```[48.828566875440806', '2.3272997082613656', 'Alésia']```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "7fc944fc",
   "metadata": {},
   "outputs": [],
   "source": [
    "def split_line(l):\n",
    "    pass\n",
    "\n",
    "split_line('48.828566875440806     , 2.3272997082613656, Alésia \\n')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f56e2ade",
   "metadata": {},
   "source": [
    "Voici une correction possible.\n",
    "\n",
    "```{toggle} Correction.\n",
    "\n",
    "```{code}\n",
    "#version brutale\n",
    "def split_line(l):\n",
    "    elts = l.split(\",\")\n",
    "    elts[0] = elts[0].strip()\n",
    "    elts[1] = elts[1].strip()\n",
    "    elts[2] = elts[2].strip()\n",
    "    return elts\n",
    "\n",
    "#version badass\n",
    "def split_line(l):\n",
    "    return [e.strip() for e in l.split(\",\")]\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "87d8a0e6",
   "metadata": {
    "tags": [
     "remove-cell"
    ]
   },
   "outputs": [],
   "source": [
    "def split_line(l):\n",
    "    return [e.strip() for e in l.split(\",\")]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1a940120",
   "metadata": {},
   "source": [
    "**Question** : Nous savons séparer correctement une ligne, nous allons maintenant réaliser l'oppération pour toutes les lignes du fichier. Faites une fonction `clear_lines(lines)`, cette fonction prend en paramètre une liste de lignes (celle produite par la fonction `read_file`) et applique la fonction `split_line` sur chaque ligne.\n",
    "\n",
    "Partant de \n",
    "```\n",
    "['48.80350127856915, 2.3174291790534154, Bagneux - Lucie Aubrac \\n',\n",
    " '48.80991722995029, 2.317686671122904, Barbara \\n',\n",
    " '48.81862126138922, 2.319703692309543, Mairie de Montrouge \\n',\n",
    " \"48.823057475209445, 2.32596933256901, Porte d'Orléans \\n\",\n",
    " '48.828566875440806     , 2.3272997082613656, Alésia \\n',\n",
    " ...\n",
    "  '48.893987070119195, 2.3478658138599524, Simplon\\n',\n",
    " '48.898311313785584, 2.345121624270384, Porte de Clignancourt\\n']\n",
    " ```\n",
    "\n",
    "On veut obtenir une liste de listes\n",
    "```\n",
    "[['48.80350127856915', '2.3174291790534154', 'Bagneux - Lucie Aubrac'], ['48.80991722995029', '2.317686671122904', 'Barbara'], ['48.81862126138922', '2.319703692309543', 'Mairie de Montrouge'], ['48.823057475209445', '2.32596933256901', \"Porte d'Orléans\"], ['48.828566875440806', '2.3272997082613656', 'Alésia'], \n",
    "...\n",
    "['48.893987070119195', '2.3478658138599524', 'Simplon'], ['48.898311313785584', '2.345121624270384', 'Porte de Clignancourt']]\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "76ca0e3d",
   "metadata": {},
   "source": [
    "```{code}\n",
    "def clear_lines(lines):\n",
    "    pass\n",
    "\n",
    "lines = read_file(\"datas/ligne4.txt\")\n",
    "lines = clear_lines(lines)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6c3ffee4",
   "metadata": {},
   "source": [
    "Voici une correction possible.\n",
    "\n",
    "```{toggle} Correction.\n",
    "\n",
    "```{code}\n",
    "def clear_lines(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        clines.append(split_line(l))\n",
    "    return clines\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "16b8f51d",
   "metadata": {
    "tags": [
     "remove-cell"
    ]
   },
   "outputs": [],
   "source": [
    "def clear_lines(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        clines.append(split_line(l))\n",
    "    return clines"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a2e3660f",
   "metadata": {},
   "source": [
    "**Réorganisez votre code** : Nous avons maintenant un bon début. Réorganisez votre fichier. Vous ne devez conserver que le minimum. Au début du fichier vous devez avoir toutes les définitions de fonctions et à la toute fin, le code exécuté.\n",
    "\n",
    "Il est important de ne pas garder les tests intermédiaires. Les commentaires doivent être brefs, rien de supperflus. Il faut que ce soit simple à lire."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b8f15df1",
   "metadata": {},
   "source": [
    "Voici ce que devrait contenir votre fichier `main.py` à ce stade.\n",
    "\n",
    "```{toggle} Correction.\n",
    "\n",
    "```{code}\n",
    "# Lecture d'un fichier de données texte.\n",
    "def read_file(name):\n",
    "    lines = \"\"\n",
    "    with open(name) as f:\n",
    "        lines = f.readlines()\n",
    "    return lines\n",
    "    \n",
    "\n",
    "# Séparation des données d'une ligne et suppression des caractères blancs.\n",
    "def split_line(l):\n",
    "    return [e.strip() for e in l.split(\",\")]\n",
    "    \n",
    "\n",
    "# Création d'une liste contenant toutes les informations des stations.\n",
    "def clear_lines(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        clines.append(split_line(l))\n",
    "    return clines\n",
    "    \n",
    "lines = read_file(\"datas/ligne4.txt\")\n",
    "lines = clear_lines(lines)\n",
    "print(lines)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5d1199cb",
   "metadata": {},
   "source": [
    "## Partie 2, préparer les données\n",
    "\n",
    "Certaines données sont corrompues. Dans un premier temps, nous allons nous contenter de les supprimer.\n",
    "\n",
    "**Question** : Réalisez une fonction `filter_incomplete_lines(lines)` qui prend en paramètre une liste de stations et renvoie une nouvelle liste, contenant uniquement les stations pour lesquelles toutes les informations sont complètes. Autrement dit, une station de ce type `['', '2.329089014624251', 'Vavin']` doit être supprimée car la latitude n'est pas renseignée.\n",
    "\n",
    "Il devrait rester 21 stations après cette oppération."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f532807f",
   "metadata": {},
   "source": [
    "```{code}\n",
    "def filter_incomplete_lines(lines):\n",
    "    pass\n",
    "\n",
    "lines = read_file(\"datas/ligne4.txt\")\n",
    "lines = clear_lines(lines)\n",
    "lines = filter_incomplete_lines(lines)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f030d8f",
   "metadata": {},
   "source": [
    "Voici une correction possible.\n",
    "\n",
    "```{toggle} Correction.\n",
    "\n",
    "```{code}\n",
    "#version simple\n",
    "def filter_incomplete_lines(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        if l[0] != \"\" and l[1] != \"\" and l[2] != \"\":\n",
    "            clines.append(l)\n",
    "    return clines\n",
    "\n",
    "#version badass\n",
    "def filter_incomplete_lines(lines):\n",
    "    return [l for l in lines if l[0] != \"\" and l[1] != \"\" and l[2] != \"\"]\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "0b3ab297",
   "metadata": {
    "tags": [
     "remove-cell"
    ]
   },
   "outputs": [],
   "source": [
    "def filter_incomplete_lines(lines):\n",
    "    return [l for l in lines if l[0] != \"\" and l[1] != \"\" and l[2] != \"\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "06fd142b",
   "metadata": {},
   "source": [
    "Parmi les données concernant les stations, la latitude et la longitude sont des nombres à virgule. Actuellement les données sont stockées sous forme de chaines de caractères, il est nécessaire de les convertir. \n",
    "\n",
    "**Question** : Réalisez une fonction `convert_to_float(lines)` qui prend en paramètre une liste de stations (comme celle obtenue après la fonction `filter_incomplete_lines`) et qui renvoie une nouvelle liste de stations dans laquelle, la latitude et la longitude ont été transformé en nombres à virgule."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0121c18f",
   "metadata": {},
   "source": [
    "```{code}\n",
    "def convert_to_float(lines):\n",
    "    pass\n",
    "\n",
    "lines = read_file(\"datas/ligne4.txt\")\n",
    "lines = clear_lines(lines)\n",
    "lines = filter_incomplete_lines(lines)\n",
    "lines = convert_to_float(lines)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bc22ab68",
   "metadata": {},
   "source": [
    "Voici une correction possible.\n",
    "\n",
    "```{toggle} Correction.\n",
    "\n",
    "```{code}\n",
    "def convert_to_float(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        clines.append([float(l[0]), float(l[1]), l[2]])\n",
    "    return clines\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "01bb5909",
   "metadata": {
    "tags": [
     "remove-cell"
    ]
   },
   "outputs": [],
   "source": [
    "def convert_to_float(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        clines.append([float(l[0]), float(l[1]), l[2]])\n",
    "    return clines"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "74581f06",
   "metadata": {},
   "source": [
    "**Réorganisez votre code** : voici à quoi devrait ressembler votre code.\n",
    "\n",
    "\n",
    "```{toggle} Correction.\n",
    "\n",
    "```{code}\n",
    "# Lecture d'un fichier de données texte.\n",
    "def read_file(name):\n",
    "    lines = \"\"\n",
    "    with open(name) as f:\n",
    "        lines = f.readlines()\n",
    "    return lines\n",
    "\n",
    "\n",
    "# Séparation des données d'une ligne et suppression des caractères blancs.\n",
    "def split_line(l):\n",
    "    return [e.strip() for e in l.split(\",\")]\n",
    "\n",
    "\n",
    "# Création d'une liste contenant toutes les informations des stations.\n",
    "def clear_lines(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        clines.append(split_line(l))\n",
    "    return clines\n",
    "\n",
    "# Suppression des lignes incomplètes.\n",
    "def filter_incomplete_lines(lines):\n",
    "    return [l for l in lines if l[0] != \"\" and l[1] != \"\" and l[2] != \"\"]\n",
    "\n",
    "# Conversion de la latitude et longitude en float.\n",
    "def convert_to_float(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        clines.append([float(l[0]), float(l[1]), l[2]])\n",
    "    return clines\n",
    "\n",
    "lines = read_file(\"datas/ligne4.txt\")\n",
    "lines = clear_lines(lines)\n",
    "lines = filter_incomplete_lines(lines)\n",
    "lines = convert_to_float(lines)\n",
    "\n",
    "print(lines)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0a82dab2",
   "metadata": {},
   "source": [
    "## Partie 3, création de la carte\n",
    "\n",
    "C'est le moment d'utiliser folium et donc d'importer le module. La bonne pratique veut que les imports soient fait dans les toutes premières lignes d'un fichier Python. Ajoutez donc l'import `import folium`. Exécutez votre programme. La première fois avec Replit, vous devriez voir l'installation du package. \n",
    "\n",
    "Si l'installation du module fonctionne correctement, nous allons pouvoir tester folium avec les trois lignes suivantes. Un fichier `ligne4.html` devrait être créé. Téléchargez et ouvrez le avec navigateur. Il devrait contenir la carte de Paris.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ddf2f39b",
   "metadata": {},
   "source": [
    "```{code}\n",
    "import folium\n",
    "m = folium.Map((48.85381285231611, 2.3449980166801163), zoom_start=13)\n",
    "m.save(\"ligne4.html\")\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca9e8379",
   "metadata": {},
   "source": [
    "Nous allons tenter d'ajouter un unique marqueur sur la carte pour le moment.\n",
    "\n",
    "**Question** : Réalisez une fonction `add_marker(l, map)` qui prend en paramètre la liste des informations concernant une station, ainsi qu'une carte folium et ajoute sur celle-ci un marqueur aux bonnes coordonnées GPS et avec le nom de la station (dans le popup).\n",
    "\n",
    "Voici pour mémoire la manière dont on ajoute un marqueur. Bien qu'on ne comprenne pas encore les subtilités de cette fonction, vous devriez pouvoir l'adapter pour votre usage.\n",
    "\n",
    "```{code}\n",
    "folium.Marker(\n",
    "    location=(48, 2),\n",
    "    popup=\"nom\",\n",
    "    icon=folium.Icon(color=\"blue\"),\n",
    "  ).add_to(map)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "92d1be68",
   "metadata": {},
   "source": [
    "```{code}\n",
    "def add_marker(l, m):\n",
    "    pass\n",
    "\n",
    "m = folium.Map((48.85381285231611, 2.3449980166801163), zoom_start=13)\n",
    "add_marker(lines[0], m)\n",
    "m.save(\"ligne4.html\")\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "54ab83a3",
   "metadata": {},
   "source": [
    "Voici une correction possible.\n",
    "\n",
    "```{toggle} Correction.\n",
    "\n",
    "```{code}\n",
    "def add_marker(l, m):\n",
    "    lat = l[0]\n",
    "    lon = l[1]\n",
    "    name = l[2]\n",
    "    folium.Marker(\n",
    "        location=(lat, lon),\n",
    "        popup=name,\n",
    "        icon=folium.Icon(color=\"blue\"),\n",
    "    ).add_to(m)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "86b9f16a",
   "metadata": {
    "tags": [
     "remove-cell"
    ]
   },
   "outputs": [],
   "source": [
    "def add_marker(l, m):\n",
    "    lat = l[0]\n",
    "    lon = l[1]\n",
    "    name = l[2]\n",
    "    folium.Marker(\n",
    "        location=(lat, lon),\n",
    "        popup=name,\n",
    "        icon=folium.Icon(color=\"blue\"),\n",
    "    ).add_to(m)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "417dbc03",
   "metadata": {},
   "source": [
    "Nous avons tout ce qu'il nous faut pour ajouter toutes les stations de métro.\n",
    "\n",
    "**Question** : Créez une fonction `add_markers(lines, m)` qui prend en paramètre une liste de stations ainsi qu'une carte folium. La fonction ajoute tous les marqueurs de stations sur la carte."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bf372d94",
   "metadata": {},
   "source": [
    "```{code}\n",
    "def add_markers(lines, m):\n",
    "    pass\n",
    "\n",
    "m = folium.Map((48.85381285231611, 2.3449980166801163), zoom_start=13)\n",
    "add_markers(lines, m)\n",
    "m.save(\"ligne4.html\")\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9e815061",
   "metadata": {},
   "source": [
    "Voici une correction possible.\n",
    "\n",
    "```{toggle} Correction.\n",
    "\n",
    "```{code}\n",
    "def add_markers(lines, m):\n",
    "    for l in lines:\n",
    "        add_marker(l, m)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "bbfbd872",
   "metadata": {
    "tags": [
     "remove-cell"
    ]
   },
   "outputs": [],
   "source": [
    "def add_markers(lines, m):\n",
    "    for l in lines:\n",
    "        add_marker(l, m)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5aae07fa",
   "metadata": {},
   "source": [
    "**Réorganiser votre code** : voici à quoi il devrait ressembler.\n",
    "\n",
    "\n",
    "```{toggle} Correction.\n",
    "\n",
    "```{code}\n",
    "import folium\n",
    "\n",
    "# Lecture d'un fichier de données texte.\n",
    "def read_file(name):\n",
    "    lines = \"\"\n",
    "    with open(name) as f:\n",
    "        lines = f.readlines()\n",
    "    return lines\n",
    "\n",
    "# Séparation des données d'une ligne et suppression des caractères blancs.\n",
    "def split_line(l):\n",
    "    return [e.strip() for e in l.split(\",\")]\n",
    "\n",
    "# Création d'une liste contenant toutes les informations des stations.\n",
    "def clear_lines(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        clines.append(split_line(l))\n",
    "    return clines\n",
    "\n",
    "# Suppression des lignes incomplètes.\n",
    "def filter_incomplete_lines(lines):\n",
    "    return [l for l in lines if l[0] != \"\" and l[1] != \"\" and l[2] != \"\"]\n",
    "\n",
    "# Conversion de la latitude et longitude en float.\n",
    "def convert_to_float(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        clines.append([float(l[0]), float(l[1]), l[2]])\n",
    "    return clines\n",
    "\n",
    "# Ajout du marqueur d'une station\n",
    "def add_marker(l, m):\n",
    "    lat = l[0]\n",
    "    lon = l[1]\n",
    "    name = l[2]\n",
    "    folium.Marker(\n",
    "        location=(lat, lon),\n",
    "        popup=name,\n",
    "        icon=folium.Icon(color=\"blue\"),\n",
    "    ).add_to(m)\n",
    "\n",
    "# Ajout de tous les marqueurs\n",
    "def add_markers(lines, m):\n",
    "    for l in lines:\n",
    "        add_marker(l, m)\n",
    "\n",
    "lines = read_file(\"datas/ligne4.txt\")\n",
    "lines = clear_lines(lines)\n",
    "lines = filter_incomplete_lines(lines)\n",
    "lines = convert_to_float(lines)\n",
    "\n",
    "m = folium.Map((48.85381285231611, 2.3449980166801163), zoom_start=13)\n",
    "add_markers(lines, m)\n",
    "m.save(\"ligne4.html\")\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "27bf63ce",
   "metadata": {},
   "source": [
    "## Partie 4, compléter les données manquantes\n",
    "\n",
    "Pour terminer, nous allons dans la mesure du possible, tenter de compléter les données manquantes.\n",
    "\n",
    "**Question** : Proposez une fonction `complete_lines` pour remplacer la fonction `filter_incomplete_lines`. \n",
    "\n",
    "Par exemple, plutôt que de supprimer les stations pour lesquels on ne connait pas le nom, on pourrait compléter le nom en indiquant \"Station inconnue\".\n",
    "\n",
    "Proposez une solution pour ce cas, et réfléchissez pour trouver une solution qui serait suffisamment satisfaisantes pour les latitudes et longitudes manquantes."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f847e874",
   "metadata": {},
   "source": [
    "```{code}\n",
    "def complete_lines_(lines):\n",
    "    pass\n",
    "\n",
    "lines = read_file(\"datas/ligne4.txt\")\n",
    "lines = clear_lines(lines)\n",
    "lines = complete_lines(lines)\n",
    "lines = convert_to_float(lines)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "859e031c",
   "metadata": {},
   "source": [
    "Voici une correction possible.\n",
    "\n",
    "```{toggle} Correction.\n",
    "\n",
    "```{code}\n",
    "#version de base\n",
    "def complete_lines_(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        if l[0] != \"\" and l[1] != \"\":\n",
    "            clines.append(l)\n",
    "            if l[2] == \"\":\n",
    "                clines[-1][2] = \"Station inconnue\"\n",
    "    return clines\n",
    "\n",
    "\n",
    "#version badass, Interpolation des positions manquantes à partir des deux stations voisines\n",
    "# (quand cela est possible)\n",
    "def complete_lines(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        clines.append(l)\n",
    "        if l[2] == \"\":\n",
    "            clines[-1][2] = \"Station inconnue\"\n",
    "\n",
    "    for i in range(len(clines)):\n",
    "        if clines[i][0] == \"\":\n",
    "            if i > 0 and clines[i - 1][0] != \"\":\n",
    "                if i < len(clines) - 1 and clines[i + 1][0] != \"\":\n",
    "                    clines[i][0] = (float(clines[i - 1][0]) +\n",
    "                                    float(clines[i + 1][0])) / 2\n",
    "\n",
    "    for i in range(len(clines)):\n",
    "        if clines[i][1] == \"\":\n",
    "            if i > 0 and clines[i - 1][1] != \"\":\n",
    "                if i < len(clines) - 1 and clines[i + 1][1] != \"\":\n",
    "                    clines[i][1] = (float(clines[i - 1][1]) +\n",
    "                                    float(clines[i + 1][1])) / 2\n",
    "\n",
    "    return clines\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "1c6a88af",
   "metadata": {
    "tags": [
     "remove-cell"
    ]
   },
   "outputs": [],
   "source": [
    "def complete_lines(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        clines.append(l)\n",
    "        if l[2] == \"\":\n",
    "            clines[-1][2] = \"Station inconnue\"\n",
    "\n",
    "    for i in range(len(clines)):\n",
    "        if clines[i][0] == \"\":\n",
    "            if i > 0 and clines[i - 1][0] != \"\":\n",
    "                if i < len(clines) - 1 and clines[i + 1][0] != \"\":\n",
    "                    clines[i][0] = (float(clines[i - 1][0]) +\n",
    "                                    float(clines[i + 1][0])) / 2\n",
    "\n",
    "    for i in range(len(clines)):\n",
    "        if clines[i][1] == \"\":\n",
    "            if i > 0 and clines[i - 1][1] != \"\":\n",
    "                if i < len(clines) - 1 and clines[i + 1][1] != \"\":\n",
    "                    clines[i][1] = (float(clines[i - 1][1]) +\n",
    "                                    float(clines[i + 1][1])) / 2\n",
    "\n",
    "    return clines\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8d93c024",
   "metadata": {},
   "source": [
    "**Réorganiser votre code** : voici à quoi il devrait ressembler au final. On a ajouté une fonction `main` qui regroupe tout le comportement du programme et est appelée une unique fois.\n",
    "\n",
    "\n",
    "```{toggle} Correction.\n",
    "\n",
    "```{code}\n",
    "import folium\n",
    "\n",
    "# Lecture d'un fichier de données texte.\n",
    "def read_file(name):\n",
    "    lines = \"\"\n",
    "    with open(name) as f:\n",
    "        lines = f.readlines()\n",
    "    return lines\n",
    "\n",
    "# Séparation des données d'une ligne et suppression des caractères blancs.\n",
    "def split_line(l):\n",
    "    return [e.strip() for e in l.split(\",\")]\n",
    "\n",
    "# Création d'une liste contenant toutes les informations des stations.\n",
    "def clear_lines(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        clines.append(split_line(l))\n",
    "    return clines\n",
    "\n",
    "# Suppression des lignes incomplètes.\n",
    "def filter_incomplete_lines(lines):\n",
    "    return [l for l in lines if l[0] != \"\" and l[1] != \"\" and l[2] != \"\"]\n",
    "\n",
    "# Interpolation des positions manquantes à partir des deux stations voisines (quand cela est possible)\n",
    "def complete_lines(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        clines.append(l)\n",
    "        if l[2] == \"\":\n",
    "            clines[-1][2] = \"Station inconnue\"\n",
    "\n",
    "    for i in range(len(clines)):\n",
    "        if clines[i][0] == \"\":\n",
    "            if i > 0 and clines[i - 1][0] != \"\":\n",
    "                if i < len(clines) - 1 and clines[i + 1][0] != \"\":\n",
    "                    clines[i][0] = (float(clines[i - 1][0]) +\n",
    "                                    float(clines[i + 1][0])) / 2\n",
    "\n",
    "    for i in range(len(clines)):\n",
    "        if clines[i][1] == \"\":\n",
    "            if i > 0 and clines[i - 1][1] != \"\":\n",
    "                if i < len(clines) - 1 and clines[i + 1][1] != \"\":\n",
    "                    clines[i][1] = (float(clines[i - 1][1]) +\n",
    "                                    float(clines[i + 1][1])) / 2\n",
    "\n",
    "    return clines\n",
    "\n",
    "# Conversion de la latitude et longitude en float.\n",
    "def convert_to_float(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        clines.append([float(l[0]), float(l[1]), l[2]])\n",
    "    return clines\n",
    "\n",
    "# Ajout du marqueur d'une station\n",
    "def add_marker(l, m):\n",
    "    lat = l[0]\n",
    "    lon = l[1]\n",
    "    name = l[2]\n",
    "    folium.Marker(\n",
    "        location=(lat, lon),\n",
    "        popup=name,\n",
    "        icon=folium.Icon(color=\"blue\"),\n",
    "    ).add_to(m)\n",
    "\n",
    "# Ajout de tous les marqueurs\n",
    "def add_markers(lines, m):\n",
    "    for l in lines:\n",
    "        add_marker(l, m)\n",
    "\n",
    "def main():\n",
    "    lines = read_file(\"../_static/datas/ligne4.txt\")\n",
    "    lines = clear_lines(lines)\n",
    "    lines = complete_lines(lines)\n",
    "    lines = convert_to_float(lines)\n",
    "\n",
    "    m = folium.Map((48.85381285231611, 2.3449980166801163), zoom_start=13)\n",
    "    add_markers(lines, m)\n",
    "    m.save(\"ligne4.html\")\n",
    "\n",
    "main()\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "ef454c67",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "import folium\n",
    "\n",
    "# Lecture d'un fichier de données texte.\n",
    "def read_file(name):\n",
    "    lines = \"\"\n",
    "    with open(name) as f:\n",
    "        lines = f.readlines()\n",
    "    return lines\n",
    "\n",
    "# Séparation des données d'une ligne et suppression des caractères blancs.\n",
    "def split_line(l):\n",
    "    return [e.strip() for e in l.split(\",\")]\n",
    "\n",
    "# Création d'une liste contenant toutes les informations des stations.\n",
    "def clear_lines(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        clines.append(split_line(l))\n",
    "    return clines\n",
    "\n",
    "# Suppression des lignes incomplètes.\n",
    "def filter_incomplete_lines(lines):\n",
    "    return [l for l in lines if l[0] != \"\" and l[1] != \"\" and l[2] != \"\"]\n",
    "\n",
    "# Interpolation des positions manquantes à partir des deux stations voisines (quand cela est possible)\n",
    "def complete_lines(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        clines.append(l)\n",
    "        if l[2] == \"\":\n",
    "            clines[-1][2] = \"Station inconnue\"\n",
    "\n",
    "    for i in range(len(clines)):\n",
    "        if clines[i][0] == \"\":\n",
    "            if i > 0 and clines[i - 1][0] != \"\":\n",
    "                if i < len(clines) - 1 and clines[i + 1][0] != \"\":\n",
    "                    clines[i][0] = (float(clines[i - 1][0]) +\n",
    "                                    float(clines[i + 1][0])) / 2\n",
    "\n",
    "    for i in range(len(clines)):\n",
    "        if clines[i][1] == \"\":\n",
    "            if i > 0 and clines[i - 1][1] != \"\":\n",
    "                if i < len(clines) - 1 and clines[i + 1][1] != \"\":\n",
    "                    clines[i][1] = (float(clines[i - 1][1]) +\n",
    "                                    float(clines[i + 1][1])) / 2\n",
    "\n",
    "    return clines\n",
    "\n",
    "# Conversion de la latitude et longitude en float.\n",
    "def convert_to_float(lines):\n",
    "    clines = []\n",
    "    for l in lines:\n",
    "        clines.append([float(l[0]), float(l[1]), l[2]])\n",
    "    return clines\n",
    "\n",
    "# Ajout du marqueur d'une station\n",
    "def add_marker(l, m):\n",
    "    lat = l[0]\n",
    "    lon = l[1]\n",
    "    name = l[2]\n",
    "    folium.Marker(\n",
    "        location=(lat, lon),\n",
    "        popup=name,\n",
    "        icon=folium.Icon(color=\"blue\"),\n",
    "    ).add_to(m)\n",
    "\n",
    "# Ajout de tous les marqueurs\n",
    "def add_markers(lines, m):\n",
    "    for l in lines:\n",
    "        add_marker(l, m)\n",
    "\n",
    "def main():\n",
    "    lines = read_file(\"../_static/datas/ligne4.txt\")\n",
    "    lines = clear_lines(lines)\n",
    "    lines = complete_lines(lines)\n",
    "    lines = convert_to_float(lines)\n",
    "    print(lines)\n",
    "\n",
    "    m = folium.Map((48.85381285231611, 2.3449980166801163), zoom_start=13)\n",
    "    add_markers(lines, m)\n",
    "    m.save(\"ligne4.html\")\n",
    "\n",
    "#main()"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Edit Metadata",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
